package com.kingre.et.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.math.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.kingre.et.Constants;
import com.kingre.et.dao.IDimensioScoreDAO;
import com.kingre.et.dao.IDimensionalityDAO;
import com.kingre.et.dao.IQuestionnaireDAO;
import com.kingre.et.dao.IRawdataDAO;
import com.kingre.et.dao.IUserDAO;
import com.kingre.et.model.DimensioScore;
import com.kingre.et.model.Dimensionality;
import com.kingre.et.model.Questionnaire;
import com.kingre.et.model.Rawdata;
import com.kingre.et.model.User;
import com.kingre.et.service.IQuestionService;
import com.kingre.et.util.FormulaUtils;

@Transactional
public class QuestionServiceImpl implements IQuestionService {
    @Autowired
    private IUserDAO userDAO;
    @Autowired
    private IQuestionnaireDAO questionnaireDAO;
    @Autowired
    private IRawdataDAO rawdataDAO;
    @Autowired
    private IDimensionalityDAO dimensionalityDAO;
    @Autowired
    private IDimensioScoreDAO dimensioScoreDAO;

    private int getRandomQuestionId(List<Integer> exId, int max) {
        int random = RandomUtils.nextInt(max) + 1;
        for (int id : exId) {
            if (random == id)
                return getRandomQuestionId(exId, max);
            else
                continue;
        }
        return random;
    }

    @Override
    public List<Questionnaire> start(Integer userId) {
        User user = userDAO.get(userId);
        List<Integer> listId = new ArrayList<Integer>();
        List<Questionnaire> questions = new ArrayList<Questionnaire>();
        Set<Rawdata> rawdatas = user.getRawdata();
        if (rawdatas != null && rawdatas.size() >= Constants.COUNT_QUESTION)
            return questions;
        for (Rawdata rawdata : rawdatas)
            listId.add(rawdata.getQuestion().getId());
        for (int i = 0; i < Constants.COUNT_PAGE; i++) {
            int questionId = getRandomQuestionId(listId, Constants.COUNT_QUESTION);
            Questionnaire question = questionnaireDAO.get(questionId);
            question.setValue(rawdataDAO.getValue(user, question.getId()));
            questions.add(question);
            listId.add(question.getId());
            if (listId.size() >= Constants.COUNT_QUESTION)
                break;
        }
        return questions;
    }

    @Override
    public List<Questionnaire> next(Integer userId, String[] questionId, String[] questionValue) {
        User user = userDAO.get(userId);
        for (int i = 0; i < questionId.length; i++) {
            int qId = Integer.parseInt(questionId[i]);
            int qVal = Integer.parseInt(questionValue[i]);
            Questionnaire question = questionnaireDAO.get(qId);
            int standardScore = FormulaUtils.generatorStandardScore(qVal, question.getMeanScore(), question.getSd());

            Rawdata rawdata = rawdataDAO.findByUserIndex(user, qId);

            if (rawdata == null) {
                rawdata = new Rawdata(user, question, qVal, standardScore, new Date());
                user.addRawdata(rawdata);
            } else {
                rawdata.setOriginalScore(qVal);
                rawdata.setStandardScore(standardScore);
                rawdata.setActionTime(new Date());
            }
            rawdataDAO.save(rawdata);
        }

        List<Questionnaire> questions = start(userId);
        if (questions == null || questions.isEmpty() || questions.size() == 0) {
            saveDimensioScore(user);
        }
        return questions;
    }

    @Override
    public int getPage(Integer userId) {
        User user = userDAO.get(userId);
        Set<Rawdata> rawdatas = user.getRawdata();
        return rawdatas == null ? 1 : (rawdatas.size() / Constants.COUNT_PAGE) + 1;
    }

    @Override
    public Questionnaire last(Integer userId) {
        User user = userDAO.get(userId);
        Set<Rawdata> rawdatas = user.getRawdata();
        int rawdataLength = rawdatas == null ? 0 : rawdatas.size();
        if (rawdataLength > 0) {
            return questionnaireDAO.get(rawdataLength);
        } else
            return questionnaireDAO.get(1);
    }

    public void saveDimensioScore(User user) {
        List<Dimensionality> dimensions = dimensionalityDAO.findAll();
        for (Dimensionality dim : dimensions) {
            Set<Questionnaire> questions = dim.getQuestion();
            Iterator<Questionnaire> iterator = questions.iterator();
            int i = 0;
            int score = 0;
            while (iterator.hasNext()) {
                Questionnaire q = iterator.next();
                score += rawdataDAO.getValue(user, q.getId());
                i++;
            }
            double avg = i > 0 ? ((score * 1.0) / i) : 0;
            System.out.println("avgScore =" + avg + ", dimensionId =" + dim.getId());
            int standardScore = FormulaUtils.generatorStandardScore(avg, dim.getMeanScore(), dim.getSd());
            DimensioScore ds = dimensioScoreDAO.findByUserDimensionality(user, dim);
            if (ds == null)
                ds = new DimensioScore(user, dim, standardScore, new Date());
            else
                ds.setStandardScore(standardScore);
            dimensioScoreDAO.save(ds);
        }
    }
}
